<template>
    <div class="common-tree comp-depts" v-loading.fullscreen="loading">
        <div class="common-tree__nect" v-show="$slots.head || $scopedSlots.head">
            <slot name="head" :loading="loading" :filters="filters" :selects="selects"></slot>
        </div>
        <div class="common-tree__body" ref="scroller">
            <div class="item item--lv0">
                <div class="name">工作队名称</div>
                <div class="space" v-show="$slots.body || $scopedSlots.body">操作</div>
            </div>
            <template v-for="dept1 in list">
                <div class="item item--lv1" :key="dept1.id" :class="{ expanded: dept1.expanded, selected: dept1.selected }" @click="expandDept(dept1)" @mouseenter="activateDept(dept1)" @mouseleave="activateDept(dept1)">
                    <div class="name">
                        <div class="expand"></div>
                        <div class="selector" @click.stop="selectDept(dept1)" v-if="select"></div>
                        <div class="text" @click.stop="selectDept(dept1)">
                            <span>{{ dept1.name }}</span>
                            <span style="margin-left: 0.5em; color: #999" v-if="dept1.type">{{ dept1.typeText }}</span>
                            <span style="margin-left: 0.5em; color: #999" v-if="dept1.type && dept1.province.id">·</span>
                            <span style="margin-left: 0.5em; color: #999" v-if="dept1.province.id">{{ dept1.province.name + dept1.city.name + dept1.county.name }}</span>
                        </div>
                    </div>
                    <div class="space" v-show="$slots.body || $scopedSlots.body">
                        <slot name="body" :loading="loading" :filters="filters" :data="dept1" :selects="selects" v-if="dept1.activated"></slot>
                    </div>
                </div>
                <template v-for="dept2 in dept1.depts">
                    <div class="item item--lv2" :key="dept2.id" :class="{ expanded: dept2.expanded, selected: dept2.selected }" @click="expandDept(dept2)" @mouseenter="activateDept(dept2)" @mouseleave="activateDept(dept2)" v-if="dept1.expanded">
                        <div class="name">
                            <div class="expand"></div>
                            <div class="selector" @click.stop="selectDept(dept2)" v-if="select"></div>
                            <div class="text" @click.stop="selectDept(dept2)">
                                <span>{{ dept2.name }}</span>
                                <span style="margin-left: 0.5em; color: #999" v-if="dept2.type">{{ dept2.typeText }}</span>
                                <span style="margin-left: 0.5em; color: #999" v-if="dept2.type && dept2.province.id">·</span>
                                <span style="margin-left: 0.5em; color: #999" v-if="dept2.province.id">{{ dept2.province.name + dept2.city.name + dept2.county.name }}</span>
                            </div>
                        </div>
                        <div class="space" v-show="$slots.body || $scopedSlots.body">
                            <slot name="body" :loading="loading" :filters="filters" :data="dept2" :selects="selects" v-if="dept2.activated"></slot>
                        </div>
                    </div>
                    <template v-for="dept3 in dept2.depts">
                        <div class="item item--lv3" :key="dept3.id" :class="{ expanded: dept3.expanded, selected: dept3.selected }" @click="expandDept(dept3)" @mouseenter="activateDept(dept3)" @mouseleave="activateDept(dept3)" v-if="dept1.expanded && dept2.expanded">
                            <div class="name">
                                <div class="expand"></div>
                                <div class="selector" @click.stop="selectDept(dept3)" v-if="select"></div>
                                <div class="text" @click.stop="selectDept(dept3)">
                                    <span>{{ dept3.name }}</span>
                                    <span style="margin-left: 0.5em; color: #999" v-if="dept3.type">{{ dept3.typeText }}</span>
                                    <span style="margin-left: 0.5em; color: #999" v-if="dept3.type && dept3.province.id">·</span>
                                    <span style="margin-left: 0.5em; color: #999" v-if="dept3.province.id">{{ dept3.province.name + dept3.city.name + dept3.county.name }}</span>
                                </div>
                            </div>
                            <div class="space" v-show="$slots.body || $scopedSlots.body">
                                <slot name="body" :loading="loading" :filters="filters" :data="dept3" :selects="selects" v-if="dept3.activated"></slot>
                            </div>
                        </div>
                        <template v-for="dept4 in dept3.depts">
                            <div class="item item--lv4" :key="dept4.id" :class="{ expanded: dept4.expanded, selected: dept4.selected }" @click="expandDept(dept4)" @mouseenter="activateDept(dept4)" @mouseleave="activateDept(dept4)" v-if="dept1.expanded && dept2.expanded && dept3.expanded">
                                <div class="name">
                                    <div class="expand"></div>
                                    <div class="selector" @click.stop="selectDept(dept4)" v-if="select"></div>
                                    <div class="text" @click.stop="selectDept(dept4)">
                                        <span>{{ dept4.name }}</span>
                                        <span style="margin-left: 0.5em; color: #999" v-if="dept4.type">{{ dept4.typeText }}</span>
                                        <span style="margin-left: 0.5em; color: #999" v-if="dept4.type && dept4.province.id">·</span>
                                        <span style="margin-left: 0.5em; color: #999" v-if="dept4.province.id">{{ dept4.province.name + dept4.city.name + dept4.county.name }}</span>
                                    </div>
                                </div>
                                <div class="space" v-show="$slots.body || $scopedSlots.body">
                                    <slot name="body" :loading="loading" :filters="filters" :data="dept4" :selects="selects" v-if="dept4.activated"></slot>
                                </div>
                            </div>
                            <template v-for="dept5 in dept4.depts">
                                <div class="item item--lv5" :key="dept5.id" :class="{ expanded: dept5.expanded, selected: dept5.selected }" @click="expandDept(dept5)" @mouseenter="activateDept(dept5)" @mouseleave="activateDept(dept5)" v-if="dept1.expanded && dept2.expanded && dept3.expanded && dept4.expanded">
                                    <div class="name">
                                        <div class="expand"></div>
                                        <div class="selector" @click.stop="selectDept(dept5)" v-if="select"></div>
                                        <div class="text" @click.stop="selectDept(dept5)">
                                            <span>{{ dept5.name }}</span>
                                            <span style="margin-left: 0.5em; color: #999" v-if="dept5.type">{{ dept5.typeText }}</span>
                                            <span style="margin-left: 0.5em; color: #999" v-if="dept5.type && dept5.province.id">·</span>
                                            <span style="margin-left: 0.5em; color: #999" v-if="dept5.province.id">{{ dept5.province.name + dept5.city.name + dept5.county.name }}</span>
                                        </div>
                                    </div>
                                    <div class="space" v-show="$slots.body || $scopedSlots.body">
                                        <slot name="body" :loading="loading" :filters="filters" :data="dept5" :selects="selects" v-if="dept5.activated"></slot>
                                    </div>
                                </div>
                            </template>
                        </template>
                    </template>
                </template>
            </template>
        </div>
        <div class="common-tree__foot" v-show="$slots.foot || $scopedSlots.foot">
            <slot name="foot" :loading="loading" :filters="filters" :selects="selects"></slot>
        </div>
    </div>
</template>

<script>
    import mixin from "../mixin";
    import { object, array, string, int, session } from "../util";
    export default {
        name: "comp-depts",
        mixins: [mixin],
        props: {
            expanded: { type: Boolean, default: false },
            select: { type: Boolean, default: false },
            link: { type: Boolean, default: false },
        },
        data: () => ({
            loading: false,
            filters: {
                linage: 10000,
                page: 1,
                total: 0,
            },
            list: [],
            selects: [],
            expands: [],
            scrollTop: 0,
        }),
        methods: {
            reset(deep) {
                let data = deep ? {} : object(session([this.env.key, this.$options.name, "filters", this.$route.fullPath]));
                this.filters = Object.assign(this.$options.data().filters, data);
                this.expands = deep ? [] : array(session([this.env.key, this.$options.name, "expands", this.$route.fullPath]));
                this.scrollTop = deep ? 0 : this.$refs.scroller.scrollTop;
                this.search(true);
            },
            validate() {
                let filters = this.filters;
                let expands = this.expands;
                filters.total = Math.max(int(filters.total), 0);
                filters.linage = Math.max(int(filters.linage), 1);
                filters.page = Math.max(Math.min(int(filters.page), Math.ceil(filters.total / filters.linage)), 1);
                session([this.env.key, this.$options.name, "filters", this.$route.fullPath], filters);
                session([this.env.key, this.$options.name, "expands", this.$route.fullPath], expands);
            },
            search(clean) {
                if (this.loading) return;
                if (clean) this.list = [];
                if (clean) this.selects = [];
                let filters = this.filters;
                this.validate();
                this.loading = true;
                this.plugins.user.getDepts(filters).then((res) => {
                    this.loading = false;
                    this.list = [];
                    this.selects = [];
                    if (res.code === 0) {
                        let data = res.data;
                        let map = data.list.sort((a, b) => {
                            let [a1, a2, a3] = [a.city.id, a.county.id, a.sort];
                            let [b1, b2, b3] = [b.city.id, b.county.id, b.sort];
                            return a1 === b1 ? a2 === b2 ? b3 - a3 : a2 - b2 : a1 - b1;
                        }).reduce((map, dept) => map.set(dept.id, dept), new Map());
                        let getLevel = (dept) => dept.dept.id ? getLevel(map.get(dept.dept.id)) + 1 : 1;
                        for (let dept of data.list) {
                            dept.level = getLevel(dept);
                        }
                        for (let dept of data.list) {
                            if (dept.level === 1) continue;
                            let parent = map.get(dept.dept.id);
                            if (parent) parent.depts.push(dept);
                            if (parent) dept.dept.name = parent.name;
                        }
                        for (let dept of data.list) {
                            let expand = this.expands.find((data) => data.key === dept.id);
                            if (expand) dept.expanded = expand.value;
                            else if (dept.level === 1 || dept.depts.length === 0) dept.expanded = this.expanded;
                        }
                        filters.total = 0;
                        this.list = data.list.filter((dept) => dept.level === 1);
                        this.validate();
                        this.$nextTick(() => this.$refs.scroller.scrollTop = this.scrollTop);
                    } else {
                        filters.total = 0;
                        this.validate();
                        this.$nextTick(() => this.$refs.scroller.scrollTop = this.scrollTop);
                        this.plugins.modal.toast("列表加载失败<br>" + res.code + "：" + res.msg, "error");
                    }
                });
            },
            activateDept(dept) {
                dept.activated = !dept.activated;
            },
            expandDept(dept) {
                dept.expanded = !dept.expanded;
                let index = this.expands.findIndex((data) => data.key === dept.id);
                if (index > -1) this.expands.splice(index, 1);
                this.expands.push({ key: dept.id, value: dept.expanded });
                this.validate();
            },
            selectDept(dept) {
                let select = (depts, selects) => depts.reduce((selects, dept) => {
                    if (dept.selected) selects.push(dept);
                    return select(dept.depts, selects);
                }, selects);
                if (this.select) {
                    dept.selected = !dept.selected;
                    this.selects = select(this.list, []);
                } else {
                    this.selects = [];
                    this.expandDept(dept);
                }
            },
            init() {
                this.loading = false;
                this.reset();
            },
        },
    };
</script>

<style lang="scss">
    .comp-depts {
        overflow: hidden;
    }
</style>